package com.sky.d_thread;

public class ThreadSafe {

	/**
	 Java内存模型和线程安全
	 	原子性、有序性、可见性、Happen-Before、线程安全
	 	
	 1.原子性
	 	指一个操作是不可中断的。即使是在多个线程一起执行的时候，一个操作一旦开始，就不会被其它线程干扰
	 	i ++是原子操作吗？
	 	不是，该操作执行：内存到寄存器中，在寄存器中自增，写回到内存，这三步都有可能被中断
	 
	 2.有序性
	 	在并发时，程序执行可能会出现乱序：在寄存器中执行会发生重排 OrderExample
	 	一条指令的执行：
	 		取指IF
	 		译码和取寄存器操作数ID
	 		执行或者有效地址计算EX
	 		存储器访问MEM
	 		写回WB
	 		
	 		例1：A = B + C的执行：
	 		LW R1 B -> IF ID EX MEM WB
	 		LW R2 C ->    IF ID EX MEM WB
	 	ADD R3 R1 R2->		 IF ID X EX MEM WB
	 		SW A1 E3-> 			IF X ID EX MEM WB
	 		
	 		例2：A = B + C
				D = E -F
			重派前
	 		LW RB1 B 	-> IF ID EX MEM WB
	 		LW RC1 C 	->    IF ID EX MEM WB
	 	ADD RA1 RB1 RC	->		 IF ID X EX MEM WB
	 		SW A1 RA	-> 			IF X ID EX MEM WB
	 		LW RE1 E	->			   X IF ID EX MEM WB
	 		LW RF F		->			   		IF ID EX MEM WB
	 	SUB RD1 RE RF	->				  	   IF ID X EX MEM WB 
	 		SW D1 RD	->					      IF X ID EX MEM WB
	 		
	 		重派后
	 		LW RB1 B 	-> IF ID EX MEM WB
	 		LW RC1 C 	->    IF ID EX MEM WB
	 		LW RE1 E	->		 IF ID EX MEM WB
	 	ADD RA1 RB1 RC	->		    IF ID EX MEM WB
	 		LW RF F		->			   IF ID EX MEM WB
	 		SW A1 RA	-> 			   	  IF ID EX MEM WB
	 	SUB RD1 RE RF	->				     IF ID EX MEM WB 
	 		SW D1 RD	->					    IF ID EX MEM WB
	 		
	 	指令重排可以使流水线更加顺畅
	 	
	 3.可见性
	 	指当一个线程修改了某个共享变量的值，其它线程是否能够立即知道这个修改
	 		编译器优化
	 		硬件优化（如写吸收、批操作）
	 
	 4.Happen-Before规则
	 	程序顺序原则：一个线程内保证语义的串行性
	 	volatile规则：volatile变量的写，先发生于读，这保证了volatile变量的可见性
	 	锁规则：解锁(unlock)必然发生在随后的加锁(lock)前
	 	传递性：A先于B，B先于C，那么A必然先于C
	 	线程的start()方法先于它的每一个动作
	 	线程的所有操作先于线程的终结(Thread.jion())
	 	线程的中断(interrupt())先于被中断的线程
	 	对象的构造函数执行结束先于finalize()方法
	 	
	 5.线程安全
	 	指某个函数、函数库在多线程环境中被调用时，能够正确地处理各个线程的局部变量，使程序的局部
	 	功能正确完成
	 	
	 	i ++ 在多线程下访问：
	 		线程1 -> 读 i =0 ,i ++ -> 写i = 1
	 		线程2 -> 读 i =0 ,i ++ -> 写i = 1
	 	线程2读取的数据可能还是0，会导致数据达不到预期，线程不安全
	 
	 */
}
